import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:ui' as ui;

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:path/path.dart' as path;
import 'package:super_tool_server/component/image/io_asset.dart'
    if (dart.library.io) 'package:super_tool_server/component/image/io_asset.dart'
    if (dart.library.html) 'package:super_tool_server/component/image/browser_asset.dart';

enum ResourceType {
  unknown,
  asset,
  net,
  file,
}

/// 图片组件
class ImageViewWidget extends StatelessWidget {
  @Deprecated('Use ImageViewWidget.asset ImageViewWidget.file ImageViewWidget.network')
  ImageViewWidget({
    required this.imageUrl,
    Key? key,
    this.placeHoldUrl,
    this.package,
    this.width,
    this.height,
    this.fit,
    this.placeHoldWidget,
    this.borderRadius,
    this.placeHoldPackage,
    this.color,
    this.loadingAnimation = false,
  })  : _resourceType = checkImageUrlIsNetwork(imageUrl)
            ? ResourceType.net
            : imageUrl.startsWith('assets')
                ? ResourceType.asset
                : ResourceType.unknown,
        super(key: key);

  ImageViewWidget.asset(
      {required this.imageUrl,
      Key? key,
      this.package,
      this.placeHoldUrl,
      this.placeHoldWidget,
      this.width,
      this.height,
      this.color,
      this.placeHoldPackage,
      this.borderRadius,
      this.fit,
      this.loadingAnimation = false})
      : _resourceType = ResourceType.asset,
        super(key: key);

  ImageViewWidget.file(
      {required this.imageUrl,
      Key? key,
      this.package,
      this.placeHoldUrl,
      this.placeHoldWidget,
      this.width,
      this.height,
      this.color,
      this.placeHoldPackage,
      this.borderRadius,
      this.fit,
      this.loadingAnimation = false})
      : _resourceType = ResourceType.file,
        super(key: key);

  ImageViewWidget.network(
      {required this.imageUrl,
      Key? key,
      this.package,
      this.placeHoldUrl,
      this.placeHoldWidget,
      this.placeHoldPackage,
      this.width,
      this.height,
      this.color,
      this.borderRadius,
      this.fit,
      this.loadingAnimation = false})
      : _resourceType = ResourceType.net,
        super(key: key);

  /// 图片URl
  final String imageUrl;

  /// 资源所在package本地资源
  final String? package;

  /// 占位图片URL
  final String? placeHoldUrl;

  /// 占位图片package
  final String? placeHoldPackage;

  /// 占位widget,优先于placeHoldUrl显示
  final Widget? placeHoldWidget;

  /// 图片宽度
  final double? width;

  /// 图片高度
  final double? height;

  /// 混合色
  final Color? color;

  /// 图片圆角
  final BorderRadius? borderRadius;

  /// 填充方式
  final BoxFit? fit;

  /// 是否展示加载动画
  final bool loadingAnimation;

  /// 图片资源类型
  final ResourceType _resourceType;

  static bool checkImageUrlIsNetwork(String? url) {
    if (url == null || url.isEmpty) {
      return false;
    }
    return url.startsWith('http://') ||
        url.startsWith('https://') ||
        url.startsWith('blob:http://') ||
        url.startsWith('blob:https://');
  }

  /// 初始化图片请求地址，常用于设置cdn
  static void setBasePrefix(String url) {
    setAssetPrefix(url);
  }

  bool isAssetResource(String? url) {
    if (checkImageUrlIsNetwork(url)) {
      return false;
    }

    ///asset 资源给的地址是相对路径
    return !path.isRelative(url!);
  }

  //
  // ///加载 file中的svg 资源
  // Future<Uint8List> _getSvgData(String imageUrl) async {
  //   File file = File(imageUrl);
  //   if (!file.existsSync()) {
  //     return null;
  //   }
  //   return file.readAsBytes();
  // }

  ///构建svg 图片
  Widget _buildSvgWidget() {
    if (_resourceType == ResourceType.file) {
      return svgFromFile(
        imageUrl: imageUrl,
        width: width,
        height: height,
        color: color,
        fit: fit!,
        placeholderBuilder: (context) {
          return _placeHoldWidget();
        },
      );
    }

    ///网络资源
    if (_resourceType == ResourceType.net) {
      if (kIsWeb) {
        return CachedNetworkImage(
          imageUrl: imageUrl,
          // '$prefix/packages/$package/$asset',
          color: color,
          placeholder: (
            BuildContext context,
            String url,
          ) {
            // web 没有办法调用这个方法
            // return placeholderBuilder(context);
            return Container();
          },
          fit: fit,
          width: width,
        );
      }
      return SvgPicture.network(
        imageUrl,
        width: width,
        height: height,
        color: color,
        fit: fit ?? BoxFit.cover,
        placeholderBuilder: (context) {
          return _placeHoldWidget();
        },
      );
    }
    if (_resourceType == ResourceType.asset) {
      ///本地资源
      return SvgPicture.asset(
        imageUrl,
        alignment: Alignment.center,
        color: color,
        fit: fit ?? BoxFit.cover,
        height: height,
        package: package,
        width: width,
        placeholderBuilder: (context) {
          return _placeHoldWidget();
        },
      );
    }
    assert(false);
    return Container();
  }

  ///占位图片
  Widget _placeHoldWidget() {
    if (placeHoldWidget != null) {
      return placeHoldWidget!;
    }
    if (placeHoldUrl != null && placeHoldUrl!.isNotEmpty) {
      return imageFromAsset(
        placeHoldUrl!,
        width: width,
        height: height,
        fit: fit ?? BoxFit.cover,
        package: placeHoldPackage,
      );
    }
    return Container();
  }

  ///构建非svg资源
  Widget _buildNotSvgWidget() {
    ///网络资源
    if (_resourceType == ResourceType.net && imageUrl.isNotEmpty) {
      return CachedNetworkImage(
        imageUrl: imageUrl,
        width: width,
        height: height,
        fit: fit ?? BoxFit.cover,
        fadeInDuration: loadingAnimation ? Duration(milliseconds: 500) : Duration(),
        fadeOutDuration: Duration(),
        placeholder: (context, String url) {
          return _placeHoldWidget();
        },
        errorWidget: (context, String url, error) {
          return _placeHoldWidget();
        },
      );
    }

    // if (_resourceType == ResourceType.file) {
    //   return imageFromFile(
    //     imageUrl,
    //     fit: fit ?? BoxFit.cover,
    //     width: width!,
    //     height: height!,
    //     color: color ?? null,
    //     loadingAnimation: loadingAnimation,
    //     placeHoldWidget: _placeHoldWidget(),
    //   );
    // }

    if (_resourceType == ResourceType.asset) {
      ///本地资源
      return imageFromAsset(
        imageUrl.isNotEmpty ? imageUrl : placeHoldUrl ?? '',
        fit: fit ?? BoxFit.cover,
        width: width,
        height: height,
        color: color ?? null,
        package: package,
        frameBuilder: loadingAnimation
            ? (context, child, frame, wasSynchronouslyLoaded) {
                if (wasSynchronouslyLoaded) {
                  return child;
                }

                ///图片加载动画
                return loadingAnimation
                    ? AnimatedSwitcher(
                        duration: const Duration(milliseconds: 500),
                        child: frame != null ? child : _placeHoldWidget(),
                      )
                    : _placeHoldWidget();
              }
            : null,
      );
    }
    return _placeHoldWidget();
  }

  @override
  Widget build(BuildContext context) {
    if (placeHoldUrl != null && placeHoldUrl!.length > 1) {
      ///仅支持asset中的资源
      assert(!isAssetResource(placeHoldUrl), '请使用 placeHoldWidget 自定义内容，placeHoldUrl 仅支持asset资源');
    }
    Widget childContent;
    if (imageUrl.isNotEmpty && path.extension(imageUrl) == '.svg') {
      childContent = _buildSvgWidget();

      return borderRadius != null
          ? ClipRRect(
              borderRadius: borderRadius!,
              child: childContent,
            )
          : childContent;
    }

    childContent = _buildNotSvgWidget();

    if (imageUrl.isNotEmpty) {
      return OverSizeImageWidget(
        imageSource: _resourceType,
        url: imageUrl,
        package: package ?? '',
        child: borderRadius != null
            ? ClipRRect(
                borderRadius: borderRadius!,
                child: childContent,
              )
            : childContent,
      );
    } else if (placeHoldUrl != null && placeHoldUrl!.isNotEmpty) {
      return OverSizeImageWidget(
        imageSource: ResourceType.asset,
        url: placeHoldUrl ?? '',
        package: placeHoldPackage ?? '',
        child: borderRadius != null
            ? ClipRRect(
                borderRadius: borderRadius!,
                child: childContent,
              )
            : childContent,
      );
    } else {
      return borderRadius != null
          ? ClipRRect(
              borderRadius: borderRadius!,
              child: childContent,
            )
          : childContent;
    }
  }
}

class OverSizeImageWidget extends StatelessWidget {
  OverSizeImageWidget(
      {required this.imageSource, required this.url, required this.child, this.package = '', this.alarmRatio = 1.6});

  final ResourceType imageSource;

  final String url;

  final Widget child;

  final String package;

  final double alarmRatio;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      initialData: null,
      future: _loadImage(),
      builder: (context, snapShot) {
        return snapShot.hasData ? _buildWidget(context, snapShot.data as ui.Image) : child;
      },
    );
  }

  Future<ui.Image> _loadImage() async {
    ImageStream? imageStream;

    switch (imageSource) {
      case ResourceType.asset:
        imageStream = AssetImage(url, package: package).resolve(ImageConfiguration.empty);
        break;
      case ResourceType.file:
        imageStream = FileImage(File(url)).resolve(ImageConfiguration.empty);
        break;
      case ResourceType.net:
        imageStream = NetworkImage(url).resolve(ImageConfiguration.empty);
        break;
      case ResourceType.unknown:
        break;
    }

    Completer<ui.Image> completer = Completer();

    ImageStreamListener? listener;
    listener = ImageStreamListener(
      (frame, synchronousCall) {
        final ui.Image image = frame.image;
        completer.complete(image);
        imageStream?.removeListener(listener!);
      },
    );

    imageStream?.addListener(listener);

    return completer.future;
  }

  Widget _buildWidget(BuildContext context, ui.Image image) {
    double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;

    Size childSize =
        Size((context as Element).renderObject!.paintBounds.width, context.renderObject!.paintBounds.height);

    String tip =
        '控件: [${(childSize.width * devicePixelRatio).toInt()}x${(childSize.height * devicePixelRatio).toInt()}]'
        '\n图片: (${image.width}x${image.height})';

    var fontSize = 14.0;
    if (childSize.height > 0) {
      fontSize = min(childSize.height / 3, fontSize);
    }
    if (childSize.width > 0) {
      fontSize = min(3 * childSize.width / tip.length, fontSize);
    }

    if (!kReleaseMode && !kDebugMode && _imageOversizeChecker(context, image)) {
      return Stack(
        children: [
          child,
          Container(
            alignment: Alignment.center,
            width: childSize.width,
            height: childSize.height,
            color: const Color(0x88EF5350),
            child: Text(
              tip,
              textAlign: TextAlign.center,
              style: TextStyle(color: Colors.white, fontSize: fontSize),
            ),
          )
        ],
      );
    }
    return child;
  }

  bool _imageOversizeChecker(BuildContext context, ui.Image image) {
    Size childSize =
        Size((context as Element).renderObject!.paintBounds.width, context.renderObject!.paintBounds.height);

    if (childSize.width <= 0 || childSize.height <= 0) {
      return false;
    }

    double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;

    return image.width / (childSize.width * devicePixelRatio) > alarmRatio ||
        image.height / (childSize.height * devicePixelRatio) > alarmRatio;
  }
}
